package org.dragon.interceptors;

import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.dragon.commons.Errors;
import org.dragon.commons.JsonResult;
import org.dragon.commons.Permit;
import org.dragon.commons.Web;
import org.dragon.models.Privilege;
import org.dragon.models.PrivilegeExtend;
import org.dragon.models.RedisSessionAccount;
import org.dragon.services.PrivilegeService;
import org.dragon.services.SessionAccountService;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.List;

/**
 * Author:     Zhao Yan
 * DateTime:   2023/5/17 10:53
 */
@Component
public class PrivilegeInterceptor implements HandlerInterceptor {

    @Resource
    private SessionAccountService sessionAccountService;

    @Resource
    private PrivilegeService privilegeService;

    public static final String[] WHITELISTS = {
            "/oauth/render/gitee",
            "/oauth/callback/gitee",
            "/config/site"
    };

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI();

        for (String w : WHITELISTS)
            if (Web.match(w, uri))
                return true;

        if (handler instanceof HandlerMethod h) {
            Permit permit = h.getMethodAnnotation(Permit.class);

            // 有此注解，才做权限校验
            if (permit != null) {
                String[] roles = permit.roles();
                String[] permissions = permit.permissions();

                RedisSessionAccount query = sessionAccountService.query(request);

                if (!query.check(roles, permissions)) {
                    Web.write(response, JsonResult.fail(Errors.NotPermit), HttpStatus.FORBIDDEN);
                    return false;
                }
            }

            // Privilege：权限：uri与当前账户权限的关系
            List<PrivilegeExtend> privileges = privilegeService.findAll();
            RedisSessionAccount query = sessionAccountService.query(request);

            for (PrivilegeExtend pe : privileges) {
                Privilege privilege = pe.privilege;

                if (privilege.getEnabled() && Web.match(privilege.getUri(), uri)) {
                    // 匹配成功，校验相关权限
                    if (!query.checkPermissions(pe.getPermissions())) {
                        Web.write(response, JsonResult.fail(Errors.NotPermit), HttpStatus.FORBIDDEN);
                        return false;
                    }
                }
            }
        }

        return true;
    }
}